#include <UDPServer.h>
#include "Poco/Net/SocketAddress.h"
#include "Poco/Timespan.h"
#include <iostream>
using namespace Poco::Net;

UDPServer::UDPServer(const SocketAddress& sa)
:Start(this ,&UDPServer::StartImp )
,ServeSession(this , &UDPServer::ServeSessionImp )
,iServerSocket(sa , true)
,iStopEven()
,iStatus(UDPServer::EStop)
{
}

UDPServer::~UDPServer(void)
{
	Stop();
}

void UDPServer::Stop()
{
	if (iStatus != EStart)
		return;
	iStatus = EStop;
	iStopEven.tryWait(100000);
}

void UDPServer::StartImp()
{
	
	Poco::Timespan span(250000);
	iStatus = EStart;
	while (iStatus == EStart)
	{
		if (iServerSocket.poll(span, Socket::SELECT_READ))
		{
			try
			{
				char buffer[256];
				Poco::UInt64 aSession = 0;
				SocketAddress sender;
				int n = iServerSocket.receiveFrom((char*)&aSession , sizeof(aSession), sender);

				std::cout<<"nhan  "<<n<<" byte "<<sender.toString()<<std::endl;
				//iServerSocket.sendTo(buffer, n, sender);
				ServeSession( TSessionAddress(sender , aSession ) );
			}
			catch (Poco::Exception& exc)
			{
				std::cerr << "UDPEchoServer: " << exc.displayText() << std::endl;
			}
		}
	}
}

void UDPServer::ServeSessionImp(const TSessionAddress& aSessionAddr)
{
	Poco::SharedPtr<Poco::Net::SocketAddress > aFirstPeerAddr;
	{
		if ( !(aFirstPeerAddr = iSession2FirstAddr.get(aSessionAddr.get<1>() )) )
		{
			iSession2FirstAddr.add(aSessionAddr.get<1>() , aSessionAddr.get<0>() );
			return;
		}
		else
			iSession2FirstAddr.remove(aSessionAddr.get<1>());

	}

	std::string aAddrStr = aSessionAddr.get<0>().toString();
	iServerSocket.sendTo(aAddrStr.data() , aAddrStr.length() , *aFirstPeerAddr );
	
	aAddrStr = aFirstPeerAddr->toString();
	iServerSocket.sendTo(aAddrStr.data() , aAddrStr.length() , aSessionAddr.get<0>() );


}
